﻿#if UNITY_EDITOR
using System;
using System.Text;
using System.IO;

namespace BF
{
    /// <summary> 
    /// 
    /// </summary> 
    public static class EncodingUtils
    {

        public static Encoding ascii = Encoding.ASCII;
        public static Encoding gb2312 = Encoding.GetEncoding("gb2312");
        public static Encoding utf8bom = new UTF8Encoding(true);
        public static Encoding utf8 = new UTF8Encoding(true);


        /// <summary>
        /// 统计文件属于 GBK 的 byte数
        /// </summary>
        /// <returns></returns>
        private static int CountGbk(byte[] bytes)
        {
            int count = 0; //存在GBK的byte
            byte[] buffer = bytes;
            int length = bytes.Length;
            const char head = (char)0x80; //小于127 通过 &head==0

            for (int i = 0; i < length; i++)
            {
                byte firstByte = buffer[i]; //第一个byte，GBK有两个
                if ((firstByte & head) == 0) //如果是127以下，那么就是英文等字符，不确定是不是GBK
                {
                    continue; //文件全部都是127以下字符，可能是Utf-8 或ASCII
                }
                if (i + 1 >= length) //如果是大于127，需要两字符，如果只有一个，那么文件错了，但是我也没法做什么
                {
                    break;
                }
                byte secondByte = buffer[i + 1]; //如果是GBK，那么添加GBK byte 2
                if (firstByte >= 161 && firstByte <= 247 &&
                    secondByte >= 161 && secondByte <= 254)
                {
                    count += 2;
                    i++;
                }
            }
            return count;
        }

        /// <summary>
        /// 属于 UTF8 的 byte 数
        /// </summary>
        /// <returns></returns>
        private static int CountUtf8(byte[] bytes)
        {
            int count = 0; //存在GBK的byte
            byte[] buffer = bytes;
            int length = bytes.Length;
            const char head = (char)0x80;
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    byte temp = buffer[i];
                    if (temp < 128) //  !(temp&head)
                    {
                        //utf8 一开始如果byte大小在 0-127 表示英文等，使用一byte
                        //length++; 我们记录的是和CountGBK比较
                        continue;
                    }
                    char tempHead = head;
                    int wordLength = 0; //单词长度，一个字使用多少个byte

                    while ((temp & tempHead) != 0) //存在多少个byte
                    {
                        wordLength++;
                        tempHead >>= 1;
                    }

                    if (wordLength <= 1)
                    {
                        //utf8最小长度为2
                        continue;
                    }

                    wordLength--; //去掉最后一个，可以让后面的 point大于wordLength
                    if (wordLength + i >= length)
                    {
                        break;
                    }
                    int point = 1; //utf8的这个word 是多少 byte
                                   //utf8在两字节和三字节的编码，除了最后一个 byte 
                                   //其他byte 大于127 
                                   //所以 除了最后一个byte，其他的byte &head >0
                    for (; point <= wordLength; point++)
                    {
                        byte secondChar = buffer[i + point];
                        if ((secondChar & head) == 0)
                        {
                            break;
                        }
                    }

                    if (point > wordLength)
                    {
                        count += wordLength + 1;
                        i += wordLength;
                    }
                }
            }
            return count;
        }

        /// <summary>
        /// 获取文件编码，仅支持utf-8与gb2312
        /// </summary>
        public static Encoding GetEncoding(string filepath)
        {
            byte[] bytes = File.ReadAllBytes(filepath);
            byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //带BOM 

            int countUtf8 = CountUtf8(bytes);
            if (countUtf8 == 0)
            {
                return ascii;
            }

            int countGbk = CountGbk(bytes);
            if (countUtf8 > countGbk)
            {
                if (bytes[0] == UTF8[0] && bytes[1] == UTF8[1] && bytes[2] == UTF8[2])
                {
                    return utf8bom;
                }

                return utf8;
            }
            else
            {
                return gb2312;
            }
        }

        public static void ConvertFileToUTF8(string filepath)
        {
            Encoding encoding = GetEncoding(filepath);
            string info = File.ReadAllText(filepath, encoding);
            File.WriteAllText(filepath, info, utf8bom);
        }
    }
}
#endif